package il.ac.biu.cs.grossmm.api.simple;

import javax.sip.ClientTransaction;
import javax.sip.ServerTransaction;
import javax.sip.SipException;
import javax.sip.SipStack;
import javax.sip.TransactionUnavailableException;
import javax.sip.header.CallIdHeader;
import javax.sip.message.Request;
import javax.sip.message.Response;

/**
 * Provides a way for any number of extension modules to use SIP protocol stack
 * (on the same set of transports/ports).
 * 
 * @see SipRequestProcessor
 */
public interface SipSharedProvider {
	/**
	 * This method registers the SipListenerCandidate object to this
	 * SipProvider, once registered the SIP Listener recieve events emitted from
	 * the SipProvider. Multiple listeners may be registered on the
	 * ISipSharedProvider concurrently.
	 * 
	 * @param listener
	 *            the ISipListinerCandidate to be registered with the
	 *            ISipSharedProvider.
	 */
	void addSipListener(SipRequestProcessor listener);

	/**
	 * Removes the specified SipListener from this ISipSharedProvider. This
	 * method returns silently if the SipListener is not registered with the
	 * ISipSharedProvider.
	 * 
	 * @param listener
	 *            the ISipListinerCandidate to be removed from this
	 *            ISipSharedProvider.
	 */
	void removeSipListener(SipRequestProcessor listener);

	/**
	 * Starts a new server transaction if the currently processing request was
	 * not received on an existing transaction. This method may be called only
	 * within <code>processRequest</code> method of
	 * <code>ISipListenerCandidate</code> instance attached to the instance of
	 * this interface. Calling this method causes the responce to be sent
	 * statefully (possibly creating a new dialog).
	 */
	ServerTransaction startServerTransaction();

	/**
	 * Returns the SipStack that created this <tt>SipSharedProvider</tt>. A
	 * ISipSharedProvider can only be attached to a single SipStack object that
	 * belongs to the same implementation as this ISipSharedProvider.
	 * 
	 * @see SipStack
	 * @return the SipStack that created this ISipSharedProvider.
	 */
	SipStack getSipStack();

	/**
	 * Returns a unique CallIdHeader for identifying dialogues between two SIP
	 * applications.
	 * 
	 * @return the new CallIdHeader unique within the ISipSharedProvider.
	 */
	public CallIdHeader getNewCallId();

	/**
	 * Before an application can send a new request it must first request a new
	 * client transaction to handle that request. This method is called by the
	 * application to create the new client transaction befores in order to send
	 * a request on that transaction. This methods returns a new unique client
	 * transaction which can be used to send Requests statefully.
	 * 
	 * @param request
	 *            the new Request message that is to handled statefully by the
	 *            ClientTransaction.
	 * @return a new unique client transaction.
	 * @throws javax.sip.TransactionUnavailableException
	 *             if a new transaction can not be created, for example the next
	 *             hop of the request can not be determined.
	 * @see javax.sip.ClientTransaction
	 * @since v1.1
	 */
	public ClientTransaction getNewClientTransaction(Request request)
			throws TransactionUnavailableException;

	/**
	 * Sends the Request statelessly, that is no transaction record is
	 * associated with this action. This method implies that the application is
	 * functioning as a stateless proxy, hence the underlying ISipSharedProvider
	 * acts statelessly. A stateless proxy simply forwards every request it
	 * receives downstream and discards information about the Request message
	 * once the message has been forwarded. A stateless proxy does not have any
	 * notion of a transaction.
	 * <p>
	 * Once the Request message has been passed to this method, the
	 * ISipSharedProvider will forget about this Request. No transaction
	 * semantics will be associated with the Request and the ISipSharedProvider
	 * will not handle retranmissions for the Request. If these semantics are
	 * required it is the responsibility of the application not the
	 * ISipSharedProvider.
	 * 
	 * @param request
	 *            the Request message to send statelessly
	 * @throws SipException
	 *             if the ISipSharedProvider cannot send the Request for any
	 *             reason.
	 */
	public void sendRequest(Request request) throws SipException;

	/**
	 * Sends the Response statelessly, that is no transaction record is
	 * associated with this action. This method implies that the application is
	 * functioning as either a stateless proxy or a stateless UAS.
	 * <ul>
	 * <li> Stateless proxy - A stateless proxy simply forwards every response
	 * it receives upstream and discards information about the response message
	 * once the message has been forwarded. A stateless proxy does not have any
	 * notion of a transaction.
	 * <li>Stateless UAS - A stateless UAS does not maintain transaction state.
	 * It replies to requests normally, but discards any state that would
	 * ordinarily be retained by a UAS after a response has been sent. If a
	 * stateless UAS receives a retransmission of a request, it regenerates the
	 * response and resends it, just as if it were replying to the first
	 * instance of the request. A UAS cannot be stateless unless the request
	 * processing for that method would always result in the same response if
	 * the requests are identical. Stateless UAS's do not use a transaction
	 * layer; they receive requests directly from the transport layer and send
	 * responses directly to the transport layer.
	 * </ul>
	 * 
	 * @param response
	 *            the Response to send statelessly.
	 * @throws SipException
	 *             if the ISipSharedProvider cannot send the Response for any
	 *             reason.
	 */
	public void sendResponse(Response response) throws SipException;

	/**
	 * Given a response code and a reason creates SIP response.
	 * 
	 * @param code
	 *            the response code
	 * @param reason
	 *            the reason phrase
	 * @return
	 */
	public Response createResponse(int code, String reason);

	/**
	 * Given an <code>RequestProcessException</code> instance create a SIP
	 * response
	 * 
	 * @param exception
	 *            the <code>RequestProcessException</code> instance
	 * @return SIP response
	 */
	public Response createResponse(RequestProcessException exception);

}
